/**
 * Copyright 2009 University of Washington This code is released under the GPL version 3 - with a copy of the license
 * included
 * 
 * @author Maya Hao Li
 */
package seedpod.webapp;

import java.util.Vector;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import seedpod.model.SeedpodDO;
import seedpod.model.SeedpodModel;
import seedpod.model.custom.SeedpodUser;
import seedpod.rdb.PManager;

public class LimsSession {

	public static LimsSession getSession( HttpServletRequest request ) {
		return new LimsSession( request );
	}

	private HttpSession			_session;

	private SeedpodUser			_user;

	private String				_sessionID;

	private PManager			_pmanager;

	private Vector<String>		_errorMessage;

	/** max inactive interval in minutes * */
	private int					_maxSessionLength;
	private Vector<String>		_requestPath;
	private boolean				_isNew		= true;

	private HttpServletRequest	_currRequest;

	public String[]				CACHE_PATH	= { "index.jsp", "instance.jsp", "error.jsp", "customize.jsp", "user.jsp" };

	public LimsSession(HttpServletRequest request) {
		_session = request.getSession();
		_currRequest = request;

		if ( _session.isNew() && _isNew ) init();
		else reInit();
		_isNew = false;
	}

	public void addSessionErrorMsg( String err ) {
		_errorMessage.add( err );
		_session.getAttribute( "errorMessage" );
	}

	public void addSessionErrorMsg( Vector<String> errs ) {
		_errorMessage.addAll( errs );
		_session.getAttribute( "errorMessage" );
	}

	public void cacheSeedpodObject( SeedpodDO obj ) {
		String objKey = obj.getMetaCls().getName() + "_" + obj.getOid();
		_session.setAttribute( objKey, obj );
	}

	public void clearAttribute( String sessionAtt ) {
		_session.removeAttribute( sessionAtt );

	}

	public void clearSessionErrorMsg() {
		_errorMessage = new Vector<String>();
		_session.getAttribute( "errorMessage" );
	}

	public Object getAttribute( String attName ) {
		return _session.getAttribute( attName );
	}

	public PManager getDataManager() {
		return _pmanager != null ? _pmanager : (PManager)_session.getAttribute( "PManager" );
	}

	public String getId() {
		return _sessionID;
	}

	public String getLastRequest() {
		if ( _requestPath != null ) {
			int numRequest = _requestPath.size();
			if ( numRequest > 0 ) return _requestPath.elementAt( numRequest - 1 );
		} else System.err.println( "_requestPath is null " );
		return null;
	}

	public SeedpodDO getSessionCachedObject( String clsName, int oid ) {
		String objKey = clsName + "_" + oid;
		return (SeedpodDO)_session.getAttribute( objKey );
	}

	public Vector<String> getSessionErrorMsg() {
		return _errorMessage;
	}

	public SeedpodUser getUser() {
		return (SeedpodUser)_session.getAttribute( SeedpodModel.RdbCls.USER );
	}

	@SuppressWarnings( { "unchecked" })
	private void init() {
		System.err.println( "new session params: " + _session.getId() );
		_sessionID = _session.getId();
		_maxSessionLength = _session.getMaxInactiveInterval() * 60 * 1000;

		_requestPath = (Vector)_session.getAttribute( "requestPath" );
		if ( _requestPath == null ) _requestPath = new Vector<String>();

		_errorMessage = (Vector)_session.getAttribute( "errorMessage" );
		if ( _errorMessage == null ) _errorMessage = new Vector<String>();

		_session.setAttribute( "requestPath", _requestPath );
		_session.setAttribute( "errorMessage", _errorMessage );

	}

	public void invalidate() {
		if ( _user == null ) _user = getUser();
		if ( _user != null ) {
			_user.logout();
			_session.invalidate();
		}
	}

	public boolean isActive() {
		long currentTime = System.currentTimeMillis();
		long lastAccess = _session.getLastAccessedTime();
		return !(lastAccess - currentTime > _maxSessionLength);
	}

	public boolean isAuthenticated() {
		if ( _user == null ) _user = getUser();

		return _user != null && _user.isLoggedIn();
	}

	private void keepPathVectorSmall() {
		if ( _requestPath == null ) _requestPath = new Vector<String>();

		if ( _requestPath.size() > 20 ) {
			System.err.println( "scale back request queue" );
			Vector<String> newVec = new Vector<String>();
			for ( int i = 15; i <= 20; i++ )
				newVec.add( _requestPath.elementAt( i ) );
			_requestPath = newVec;
		}
	}

	public String popRequestedURL() {
		if ( _requestPath != null ) {
			int size = _requestPath.size();
			if ( size > 0 ) return _requestPath.remove( size - 1 );
		}

		return null;
	}

	public void pushRequestedURL() {
		if ( _currRequest != null ) {
			String url = _currRequest.getRequestURI();
			String queryString = _currRequest.getQueryString();
			if ( queryString != null ) url = url + "?" + queryString;

			pushRequestedURL( url );
		}
	}

	public void pushRequestedURL( String newPath ) {
		keepPathVectorSmall();
		for ( String p : CACHE_PATH )
			if ( newPath.contains( p ) ) _requestPath.add( newPath );
	}

	@SuppressWarnings("unchecked")
	private void reInit() {
		System.err.println( "reinit param: " + _session.getId() );
		_requestPath = (Vector<String>)_session.getAttribute( "requestPath" );
		_errorMessage = (Vector<String>)_session.getAttribute( "errorMessage" );
	}

	public void setAttribute( String attName, Object attVal ) {
		_session.setAttribute( attName, attVal );
	}

	public void setDataManager( PManager manager ) {
		_pmanager = manager;
		_session.setAttribute( "PManager", manager );
	}

	public void setUser( SeedpodUser user ) {
		_user = user;
		_session.setAttribute( SeedpodModel.RdbCls.USER, user );
	}

}